﻿using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.IdentityModel.Logging;
using PLCS.App.Shared.Common;
using PLCS.Application.Contracts.EquipmentApp.Dtos;
using PLCS.Client.Service.Client;
using PLCS.Domain.Shared.Enums;
using PLCS.Shared.Common.Constant;
using RestSharp;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database;

namespace PLCS.App.Shared.Views.UserControls.Chlidren
{
    /// <summary>
    /// RotaryTable.xaml 的交互逻辑
    /// </summary>
    public partial class RotaryTable : UserControl
    {
        #region Properties

        //托盘或货物
        private Rectangle goods = new();

        //外圈⚪
        private Ellipse ellipse = new Ellipse();

        //左右上下侧边框
        private Rectangle leftline = new();

        private Rectangle rightline = new();
        private Rectangle topline = new();
        private Rectangle bottomline = new();

        //Webapi客户端
        public HttpRestClient restClient = new();

        private RequestParam requestParam;
        private SolidColorBrush bg;

        //竖放标志
        private bool verticalflag;

        private List<string> strs = new List<string>() { };

        public ICommand Command
        {
            get { return (ICommand)GetValue(CommandProperty); }
            set { SetValue(CommandProperty, value); }
        }

        public static readonly DependencyProperty CommandProperty =
            DependencyProperty.Register("Command", typeof(ICommand), typeof(RotaryTable), new UIPropertyMetadata(null));

        public object CommandParameter
        {
            get { return (object)GetValue(CommandParameterProperty); }
            set { SetValue(CommandParameterProperty, value); }
        }

        // Using a DependencyProperty as the backing store for CommandParameter.  This enables animation,styling,binding,etc...
        public static readonly DependencyProperty CommandParameterProperty =
            DependencyProperty.Register("CommandParameter", typeof(object), typeof(RotaryTable), new UIPropertyMetadata(null));

        /// <summary>
        /// 强制输入事件和属性来自FrameworkElement
        /// </summary>
        public IInputElement CommandTarget
        {
            get { return (IInputElement)GetValue(CommandTargetProperty); }
            set { SetValue(CommandTargetProperty, value); }
        }

        // Using a DependencyProperty as the backing store for CommandTarget.  This enables animation,etc...
        public static readonly DependencyProperty CommandTargetProperty =
            DependencyProperty.Register("CommandTarget", typeof(IInputElement), typeof(RotaryTable), new UIPropertyMetadata(null));

        /// <summary>
        /// 名称
        /// </summary>
        public string SName
        {
            get { return (string)GetValue(SNameProperty); }
            set { SetValue(SNameProperty, value); }
        }

        public static readonly DependencyProperty SNameProperty =
            DependencyProperty.Register("SName", typeof(string), typeof(RotaryTable), new PropertyMetadata("R101"));

        //名称改变
        //private static void OnSNameChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => (d as ConveyorLine).RefreshHaveStatus();
        /// <summary>
        /// 是否有无托盘
        /// </summary>
        public YesNo HaveStatus
        {
            get { return (YesNo)GetValue(HaveStatusProperty); }
            set { SetValue(HaveStatusProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Seat.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty HaveStatusProperty =
            DependencyProperty.Register("HaveStatus", typeof(YesNo), typeof(RotaryTable), new PropertyMetadata(YesNo.否, new PropertyChangedCallback(OnHaveChanged)));

        #endregion Properties

        #region Constructor

        public RotaryTable()
        {
            InitializeComponent();
            Background = Background ?? Brushes.DimGray;
            //小手图示
            Cursor = Cursors.Hand;
            SizeChanged += RotaryTable_SizeChanged;
            //this.Loaded += RotaryTable_Loaded;
            //Task.Run(UIChange);
            //RotateAnimation(-90);
        }

        private async void RotaryTable_Loaded(object sender, RoutedEventArgs e)
        {
            await using HubConnection hubConnection = new HubConnectionBuilder().WithUrl(AddressManager.Address + AddressManager.StationHub).Build();
            hubConnection.On<string, YesNo>("ChangeStatus", async (sname, status) =>
            {
                await System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
                {
                    if (sname == SName)
                        if (status != HaveStatus) HaveStatus = status;
                }), System.Windows.Threading.DispatcherPriority.Background);
            });
            if (hubConnection.State != HubConnectionState.Connected)
            {
                await hubConnection.StartAsync();
                await hubConnection.InvokeAsync("InitalStatus", SName);
            }
        }

        #endregion Constructor

        #region Event

        /// <summary>
        /// 重载鼠标左击时触发事件
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
        {
            base.OnMouseLeftButtonDown(e);
            //_eventAggregator.GetEvent<StationEvent>().Publish(SName);
            var command = Command;
            var parameter = CommandParameter;
            var target = CommandTarget;

            var routedCmd = command as RoutedCommand;
            if (routedCmd != null && routedCmd.CanExecute(parameter, target))
            {
                routedCmd.Execute(parameter, target);
            }
            else if (command != null && command.CanExecute(parameter))
            {
                command.Execute(parameter);
            }
        }

        /// <summary>
        /// Usercontrols size changed event
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <exception cref="NotImplementedException"></exception>
        private void RotaryTable_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            //清除所有子控件
            this.LayoutCanvas.Children.Clear();
            //鼠标悬停提示
            ToolTip = $"旋转台：{SName}";
            strs.Add(SName);
            int count = strs.Where(str => str == SName).Count();
            if (count > 1) MessageBox.Show($"Err{SName}");
            //实际宽小于高 - 认定为竖放标志
            verticalflag = LayoutCanvas.ActualWidth < LayoutCanvas.ActualHeight ? true : false;

            //左侧竖边
            leftline = new Rectangle();
            leftline.Width = verticalflag ? LayoutCanvas.ActualWidth / 10 : LayoutCanvas.ActualWidth / 20;
            leftline.Height = LayoutCanvas.ActualHeight;
            leftline.Fill = Background == Brushes.Transparent ? Brushes.DimGray : Background;
            LayoutCanvas.Children.Add(leftline);
            //右侧竖边
            rightline = new Rectangle();
            rightline.Width = verticalflag ? LayoutCanvas.ActualWidth / 10 : LayoutCanvas.ActualWidth / 20;
            rightline.Height = LayoutCanvas.ActualHeight;
            rightline.Fill = Background == Brushes.Transparent ? Brushes.DimGray : Background;
            rightline.Margin = new()
            {
                Left = LayoutCanvas.ActualWidth * (verticalflag ? 9 : 19) / (verticalflag ? 10 : 20)
            };
            LayoutCanvas.Children.Add(rightline);

            //上侧橫边
            topline = new Rectangle();
            topline.Width = this.LayoutCanvas.ActualWidth;
            topline.Height = verticalflag ? LayoutCanvas.ActualHeight / 20 : LayoutCanvas.ActualHeight / 10;
            topline.Fill = Background == Brushes.Transparent ? Brushes.DimGray : Background;
            LayoutCanvas.Children.Add(topline);
            //下侧橫边
            bottomline = new Rectangle();
            bottomline.Width = this.LayoutCanvas.ActualWidth;
            bottomline.Height = verticalflag ? LayoutCanvas.ActualHeight / 20 : LayoutCanvas.ActualHeight / 10;
            bottomline.Fill = Background == Brushes.Transparent ? Brushes.DimGray : Background;

            bottomline.Margin = new Thickness()
            {
                Top = this.LayoutCanvas.ActualHeight * (verticalflag ? 19 : 9) / (verticalflag ? 20 : 10)
            };
            LayoutCanvas.Children.Add(bottomline);

            //画个虚线⚪
            ellipse = new Ellipse();
            ellipse.Width = Math.Pow(Math.Pow(LayoutCanvas.ActualHeight, 2) + Math.Pow(LayoutCanvas.ActualWidth, 2), 0.5);
            ellipse.Height = ellipse.Width;
            //虚线
            ellipse.StrokeDashArray = new DoubleCollection(new double[] { 2, 2, 2, 2 });
            ellipse.StrokeThickness = 1;
            ellipse.Stroke = Brushes.DimGray;
            ellipse.SetValue(Canvas.LeftProperty, topline.Width / 2 - ellipse.Width / 2);
            ellipse.SetValue(Canvas.TopProperty, leftline.Height / 2 - ellipse.Height / 2);
            LayoutCanvas.Children.Add(ellipse);

            //滚筒 间隔 3
            if (verticalflag)
            {//竖放输送线 滚筒摆放
             //计算 可以放的滚筒个数
                int rattlerCount = (int)(this.LayoutCanvas.ActualHeight / (this.LayoutCanvas.ActualHeight / 20 + 3));
                for (int i = 1; i < rattlerCount; i++)
                {
                    this.LayoutCanvas.Children.Add(new Rectangle()
                    {
                        Width = this.LayoutCanvas.ActualWidth - leftline.Width * 2,
                        Height = this.LayoutCanvas.ActualHeight / 20,
                        Fill = Brushes.White,
                        RadiusX = 2, //圆角
                        RadiusY = 2,
                        Margin = new()
                        {
                            Left = leftline.Width,
                            Top = this.LayoutCanvas.ActualHeight * i / 20 + i * 3,
                        }
                    }); ;
                }
            }
            else
            {//横放输送线 滚筒摆放
                int rattlerCount = (int)(this.LayoutCanvas.ActualWidth / (this.LayoutCanvas.ActualWidth / 20 + 3));
                for (int i = 1; i < rattlerCount; i++)
                {
                    this.LayoutCanvas.Children.Add(new Rectangle()
                    {
                        Width = this.LayoutCanvas.ActualWidth / 20,
                        Height = this.LayoutCanvas.ActualHeight - topline.Height * 2,
                        Fill = Brushes.White,
                        RadiusX = 2,//圆角
                        RadiusY = 2,
                        Margin = new()
                        {
                            Top = topline.Height,
                            Left = this.LayoutCanvas.ActualWidth * i / 20 + i * 3
                        }
                    });
                }
            }

            //托盘
            goods = new Rectangle();
            goods.Width = LayoutCanvas.ActualWidth > 20 ? 20 : LayoutCanvas.ActualWidth;
            goods.Height = LayoutCanvas.ActualHeight > 20 ? 20 : LayoutCanvas.ActualHeight;
            // goods.Fill = new SolidColorBrush(Color.FromRgb(0, 229, 255));
            goods.Fill = new SolidColorBrush(Color.FromRgb(11, 112, 253));
            double left = LayoutCanvas.ActualWidth - 20 > 0 ? LayoutCanvas.ActualWidth / 2 - 10 : 0;
            double top = LayoutCanvas.ActualHeight - 20 > 0 ? LayoutCanvas.ActualHeight / 2 - 10 : 0;
            goods.Margin = new()
            {
                Left = left,
                Top = top,
            };
            goods.Visibility = HaveStatus == YesNo.否 ? Visibility.Hidden : Visibility.Visible;
            LayoutCanvas.Children.Add(goods);
        }

        /// <summary>
        /// Property HaveChanged changed event
        /// </summary>
        /// <param name="d"></param>
        /// <param name="e"></param>
        private static void OnHaveChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => (d as RotaryTable).RefreshHaveStatus();

        #endregion Event

        #region Method

        /// <summary>
        /// 刷新是否有货/托盘
        /// </summary>
        public void RefreshHaveStatus() => Dispatcher.Invoke(new Action(delegate
        {
            goods.Visibility = HaveStatus == YesNo.否 ? Visibility.Hidden : Visibility.Visible;
        }));

        #region UIChange

        /// <summary>
        /// 更改UI
        /// </summary>
        private async void UIChange()
        {
            await Dispatcher.BeginInvoke(new Action(async () =>
            {
                try
                {
                    while (true)
                    {
                        if (string.IsNullOrWhiteSpace(SName))
                        {
                            await Task.Delay(TimeSpan.FromSeconds(5));
                            continue;
                        }
                        requestParam = new RequestParam(Method.Get, $"equipment/bySName?name={SName}");
                        var apiResponse = await restClient.ExecuteAsync<EquipmentDto>(requestParam);
                        var model = apiResponse.Data;
                        if (model == null)
                        {
                            await Task.Delay(TimeSpan.FromSeconds(5));
                            continue;
                        }
                        //设备状态颜色变化
                        switch (model.Status)
                        {
                            case DeviceStatus.空闲:
                                bg = Brushes.DimGray;
                                break;

                            case DeviceStatus.忙碌:
                                bg = new SolidColorBrush(Color.FromRgb(0, 230, 118));// "#ABFF33";
                                break;

                            case DeviceStatus.故障:
                                bg = new SolidColorBrush(Color.FromRgb(255, 61, 0));
                                break;

                            default:
                                bg = Brushes.Transparent;
                                break;
                        }
                        if (this.Background.ToString() != bg.ToString())
                        {
                            Background = bg;
                            //边框颜色变化
                            bottomline.Fill = topline.Fill = rightline.Fill = leftline.Fill = Background == Brushes.Transparent ? Brushes.Gray : Background;
                        }
                        if (model.HaveStatus != HaveStatus) HaveStatus = model.HaveStatus;
                        await Task.Delay(TimeSpan.FromSeconds(1));
                    }
                }
                catch (Exception ex)
                {
                    ex = new Exception($"输送线{SName}更改界面方法发生错误：{ex.Message}");
                  //  LogHelper.LogExceptionMessage(ex);
                    await Task.Delay(5000);
                }
            }), System.Windows.Threading.DispatcherPriority.ApplicationIdle);
        }

        #endregion UIChange

        #endregion Method

        #region Animation

        /// <summary>
        /// 旋转动画
        /// </summary>
        public void RotateAnimation(double initvalue, double rotatevalue)
        {
            AnimationHelper.AngleRotateAnimation(this, initvalue, rotatevalue, 1, TimeSpan.FromSeconds(10));
        }

        //RotateTransform rotate = new RotateTransform();
        //this.RenderTransform = rotate;
        //this.RenderTransformOrigin = new Point(0.5, 0.5);//设置旋转中心 - 可以设置为控件中心
        //Storyboard story = new Storyboard();// 实例化容器时间线对象

        //DoubleAnimation da = new DoubleAnimation(0, rotatevalue, new Duration(TimeSpan.FromSeconds(3)));//实例化动画处理对象
        //da.RepeatBehavior = RepeatBehavior.Forever;
        //Storyboard.SetTarget(da, this);//对象和属性，对象是按钮，属性就是行为，旋转的行为
        //Storyboard.SetTargetProperty(da, new PropertyPath("RenderTransform.Angle"));//顺时针旋转一个角 让一个角顺时针旋转
        //story.Children.Add(da);//将这个旋转的行为(处理动画的类）添加到时间线故事板中
        //story.Begin();

        #endregion Animation
    }
}